#include <stdio.h>
#include <string.h>

#include "common.h"
#include "my_uart.h"

#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"

#include "esp_log.h"
#include "esp_intr_alloc.h"
#include "esp_task_wdt.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"


//超温报警-后端完成

/**
 * This is an example which echos any data it receives on configured UART back to the sender,
 * with hardware flow control turned off. It does not use UART driver event queue.
 *
 * - Port: configured UART
 * - Receive (Rx) buffer: on
 * - Transmit (Tx) buffer: off
 * - Flow control: off
 * - Event queue: off
 * - Pin assignment: see defines below (See Kconfig)
 */

     
/*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/

// #define BUF_SIZE (1024)
// #define RD_BUF_SIZE (BUF_SIZE)

static const int mode = OBJECT_MODE;
static const char *TAG = "temp_measurement";

static char *mode_char = "0";


// static QueueHandle_t uart0_queue;

int loop_cnt = 1;
int temprature = -99;

int reboot_delay = 0; //建议不大于30s

uint8_t do_validate(uint8_t *data, int len, int index){
    if(index >= len){
        return 0;
    }
    return data[index] + do_validate(data, len, index + 1);
}

int validate_data(uint8_t *data, int len)
{
    uint8_t validation_bit = data[len - 1];
    uint16_t my_validation = 0;
    uint8_t header = data[0];
    // for (int i = 0; i < len; i++) {
    //     printf("%02X ", data[i]);
    // }
    // printf("\n");
    if (header != 0xFE) {
        temprature = GLOBAL_EXCEPTION;
        return TRANSMIT_EXCEPTION;
    }else if (len == 0)
    {
        temprature = GLOBAL_EXCEPTION;
        return NULL_EXCEPTION;
    }else if (my_validation == 0)
    {
        // 最后一位是校验位，不算在内
        *(data + len - 1) = 0x00;

        // data现在应该包含了包头+指令+DataH+DataL+保留位 1+保留位 2+保留位 3+保留位 4
        // for (int i = 0; i < len; i++) {
        //     printf("%02X ", data[i]);
        // }
        // printf("\n");

        //最后一位是校验位，不算在内
        my_validation = do_validate(data, len, 0); 
    }
    if(data[2] == 0xFF && data[3] == 0xFF){
        temprature = GLOBAL_EXCEPTION;
        // TODO：向物联网平台报障，”传感器模式未设置，正在重新启动“。
        
        return SENSOR_EXCEPTIION;
    }
    if ((my_validation & 0xFF) != validation_bit)
    {
        printf("--------------------------------\n");
        printf("_%02X_ _%02X_ _%02X_\n", (my_validation & 0xFF), my_validation, validation_bit);
        temprature = GLOBAL_EXCEPTION;
        return TRANSMIT_EXCEPTION;
    }
    // printf("_%02X_ _%02X_ _%02X_\n", (my_validation & 0xFF), my_validation, validation_bit);
    return RUNNING;
    
}

int uart_get_temprature(void)
{
    if(temprature != -99){
        return temprature;
    }
    else{
        return -1;
    }
}

static int measure()
{
    // Configure the initial dataset
    uint8_t *data = (uint8_t *)malloc(RECV_BUF_SIZE); // 32 elements maximum for received data
    uint8_t *mode_data = (uint8_t *)malloc(SEND_BUF_SIZE); // temperature measuring mode HEX data
    uint8_t *start_sig = (uint8_t *)malloc(SEND_BUF_SIZE); // start signal to measure temperature
    
    int len = 0;

    *start_sig = 0xFA;
    *(start_sig+1) = 0xCA;
    *(start_sig+2) = 0xC4;

    vTaskDelay((HB_INTERVAL - HB_INTERVAL / UPDATE_INTERVAL * 1.0) / portTICK_PERIOD_MS); //延时100ms

    if (mode == HUMAN_MODE)
    {
        *mode_data = 0xFA;
        *(mode_data+1) = 0xC5;
        *(mode_data+2) = 0xBF;
        mode_char = "体温模式";
        /* code */
    }
    else if (mode == OBJECT_MODE)
    {
        *mode_data = 0xFA;
        *(mode_data+1) = 0xC6;
        *(mode_data+2) = 0xC0;
        mode_char = "物温模式";
        /* code */
    }
    uart_write_bytes(ECHO_UART_PORT_NUM, (const uint8_t *) mode_data, SEND_BUF_SIZE); //写入测温模式数据    
    ESP_LOGI(TAG, "-----测温模式设置成功，当前模式为：%s-----", mode_char);

    ESP_LOGI(TAG, "-----开始测温-----");

    while(true){
        // 检测传感器数据收发端口状态
        len = 0;
        int count = 0;
        int vaild_count = 0;
        uint8_t inner_flag = 0;

        if(loop_cnt == 1000){
            loop_cnt = 0;
        }

        memset(data,0,RECV_BUF_SIZE);

        while (len == 0)// 传感器没有在测温或温度校验不通过或温度为空
        {
            
            if(!(data[0]) && !(count % (HB_INTERVAL / 10 * MEASURE_INTERVAL))){
                // 发送测温检测指令  
                uart_write_bytes(ECHO_UART_PORT_NUM, (const uint8_t *) start_sig, SEND_BUF_SIZE);   
                if(!inner_flag){
                    // ESP_LOGI(TAG, "-----请求温度-----"); // 调试专用
                    inner_flag = 1;
                }
                // 接收温度值
                len = uart_read_bytes(ECHO_UART_PORT_NUM, (const uint8_t *) data, (RECV_BUF_SIZE - 1), HB_INTERVAL / portTICK_RATE_MS);
                vaild_count += 1;
            }
            if(count > 99){

                break;
            }
            count += 1; // 100ms
            vTaskDelay((HB_INTERVAL - HB_INTERVAL / UPDATE_INTERVAL * vaild_count * 1.0) / portTICK_PERIOD_MS); //延时100ms
        }
        int validate_code = validate_data(data, len);

        if(validate_code == TRANSMIT_EXCEPTION){
            ESP_LOGI(TAG, "-----温度数据校验失败，重新获取中-----");
            temprature = GLOBAL_EXCEPTION;
            memset(data, 0, RECV_BUF_SIZE);
        }else if(validate_code == NULL_EXCEPTION){
            ESP_LOGI(TAG, "-----温度数据为空，重新获取中-----");
            temprature = GLOBAL_EXCEPTION;
            memset(data, 0, RECV_BUF_SIZE);
        }else if(validate_code == SENSOR_EXCEPTIION){
            ESP_LOGI(TAG, "-----传感器模式未设置，正在重新启动-----"); //故障报警
            temprature = REBOOT_EXCEPTION;
            reboot_delay = 15; //建议小于30s
            memset(data, 0, RECV_BUF_SIZE);
            return STOP_FLAG;
        }else if(validate_code == RUNNING){
            // ESP_LOGI(TAG, "-----温度数据正常-----"); // 调试专用
        }else{
            ESP_LOGI(TAG, "-----其他异常，正在重新启动-----"); //故障报警
            temprature = REBOOT_EXCEPTION;
            reboot_delay = 10;
            memset(data, 0, RECV_BUF_SIZE);
            return STOP_FLAG;
        }

        // data[len] = '\0';

        // 调试专用
        // for (int i = 0; i < len; i++) {
        //     printf("%02X ", data[i]);
        // }
        // printf("\n");

        // 温度获取
        if(temprature != GLOBAL_EXCEPTION){
            temprature = data[2] * 100 + data[3];  
        }
        // ESP_LOGI(TAG, "温度值*100: %d", temprature); // 调试专用
        loop_cnt += 1;
        esp_task_wdt_reset();
        // printf("%d\n", loop_cnt);

        //修正延时误差
        vTaskDelay(HB_INTERVAL / VARIATE_COEFFICIENT / portTICK_PERIOD_MS); 
    }
    return 0;
}


void uart_main(void *pvParameter)
{
    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = ECHO_UART_BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    int intr_alloc_flags = 0;
    int is_task_stop = 0;

    #if CONFIG_UART_ISR_IN_IRAM
        intr_alloc_flags = ESP_INTR_FLAG_IRAM;
    #endif

    ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, RECV_BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
    ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config));
    ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));
    
    // TODO: 串口QUEUE队列和分包组包拆包 uart0_queue

    // Configure a temporary buffer for the incoming data
    // uart_pattern_queue_reset(EX_UART_NUM, 5);

    while(1){
        if(is_task_stop == STOP_FLAG){
            ESP_LOGI(TAG, "-----结束测温-----");
            ESP_LOGI(TAG, "-----请重新插拔传感器的所有引脚，并等待至少30秒-----"); // 故障提示
        printf("\n");
            vTaskDelay(reboot_delay * 1000 / portTICK_PERIOD_MS);
            // TODO: 程序结束处理
        }
        else{
            ESP_LOGI(TAG, "-----开始测温-----");
            printf("\n");
        }
        is_task_stop = measure();
    }
}

